home *** CD-ROM | disk | FTP | other *** search
/ Mac100% 1998 November / MAC100-1998-11.ISO.7z / MAC100-1998-11.ISO / オンラインソフト定点観測 / ユーティリティ / Mops 3.2.sea / Mops 3.2 / Mops ƒ / zClass < prev    next >
Text File  |  1998-06-19  |  63KB  |  2,471 lines

  1. (*    file zClass
  2.  
  3. This file is part of the PPC version of the high-level class/object
  4. implementation.  It's a "z" file - it's not target compiled, but is
  5. loaded on the PPC itself.  Some of the PPC code is target compiled in
  6. qpClass, since we need it while we're still target compiling.  I would
  7. have liked to get ALL the class implementation into qpClass, but this
  8. proved to bristle with far too many problems, so here we include
  9. everything that didn't make it, which is quite a lot.
  10.  
  11. *)
  12.  
  13.  
  14.  
  15. ¥ Here are all our various class/object formats:
  16.  
  17.  
  18. (*            ================= Object header ======================
  19.  
  20. Note if the obj is an ivar, it doesn't have a header if it's in a record,
  21. unless the ivar is indexed.  Indexed ivars always have headers, no matter
  22. what, since the indexing code relies on it.
  23.  
  24. PPC notes: we have to make some minor changes to the object header format
  25. for various reasons.
  26.  
  27. 1. As objects live in the data area, we need a back pointer to the dic
  28. entry in the code area, so methods like .ID: work.
  29.  
  30. 2. The class pointer is a 4-byte relocatable address, and we want it to
  31. be aligned.
  32.  
  33. 3. The indexed length of the object now always occupies the 4 bytes at
  34. the end of the indexed descriptor, whereas on the 68k, although we
  35. allocated 4 bytes, we normally only took notice of the low 2 bytes.
  36. We want the 4 bytes preceding the obj's data to look like a negative
  37. indexed length if the object isn't indexed.
  38.  
  39. So we end up with this layout:
  40.  
  41. 4 bytes        Back pointer to cfa of obj's dic entry (relocatable).
  42.             Zero if no dic entry, or if no name field there.
  43.  
  44. 4 bytes        Class pointer (relocatable).
  45.  
  46. 2 bytes        Self relative offset to the class pointer.
  47.             For simple objects (i.e. not embedded), this is -4.
  48.             For embedded objects, it will be more negative.  Note it
  49.             will always be negative.
  50.  
  51. 2 bytes        Self relative offset to the indexed area.  If not indexed,
  52.             this will be 2, pointing to the next byte which is the first
  53.             data byte of the object.  This means, if we erroneously try
  54.             to access the indexed area of a non-indexed object, we'll
  55.             get sent to the non-indexed data area, and try to interpret
  56.             the preceding 4 bytes as an "indexed length" (which is what
  57.             precedes a valid indexed area).  But these 4 bytes are these
  58.             two offsets, which will always appear as a negative number.
  59.             If we're doing range checking, this will always trap.
  60.             We did a similar sneaky trick on the 68k, but the field
  61.             lengths/positions were different.
  62.  
  63. (object's data starts here)
  64.  
  65. This format means that when multiply inheriting, we need 4 bytes
  66. separating each group of ivars ("embedded object"), not 2 as on
  67. the 68k.
  68.  
  69.  
  70. For indexed objects, the indexed area (after the ivars) is preceded by
  71. the indexed descriptor (xdesc) with the following format.  This format
  72. is the same as on the 68k, except that it starts off-aligned, i.e.
  73. the #elements field is 4-byte aligned.
  74.  
  75. 2 bytes        Width of indexed elements (in bytes)
  76. 4 bytes        Number of elements minus 1 (i.e. LIMIT-1).
  77.             We can check this with a trap instruction.
  78.  
  79.  
  80.  
  81.         ==============  Class dictionary entry  ================
  82.  
  83. link/name/hndlr    as for normal words - normal class hndlr is $BC1D,
  84. and for imported classes, $BC2D.
  85.  
  86. Note that the offsets are defined in 2 places, which must agree! -
  87. here, and in pNuc4.
  88.  
  89. 2 bytes            flags
  90. (note - we're now aligned)
  91.  
  92. (offs 2)    32 bytes    links to 8-way hashed method chains (relative)
  93. (offs 34)    4 bytes        link to ivar chain (relative)
  94. (offs 38)    2 bytes        padding for alignment of the n-way, and to put
  95.                         the next fields in the same place as on the 68k,
  96.                         which simplifies (findM).
  97. (offs 40)    2 bytes        non-indexed data length
  98. (offs 42)    2 bytes        width of indexed elements, or zero if not indexed
  99. (offs 44)    2 bytes        "xdispl offs" - the ivar offset where indexing starts
  100.                         (used by large_obj_arrays), or zero if none.
  101. (offs 46)    4(n+1) bytes
  102.                 n-way to superclasses (n relocatable addrs terminated by zero)
  103.  
  104. Flag bits:
  105.     $0001        "large" - indexed with > 64K elements.
  106.     $0002        class is exported from a module
  107.     $8000        class is META (we use this to terminate NW_IVsetup)
  108.  
  109. Note: on the 68k, at the class cfa there was a call to BLD, the word
  110. which built an object.  These 4 bytes also served as a unique marker
  111. identifying a class dic entry, since we did a JSR to BLD, and this
  112. always had the same bit pattern.  We treated the class handler code
  113. the same as for a colon definition, and simply BSR'd to the cfa.
  114.  
  115. On the PPC we'll really use class_h, so that a class won't
  116. look like a colon definition any more.  This is a bit more logical
  117. and shouldn't cause any problems.  In any case, we couldn't use a
  118. call to BLD as a unique marker, since calls are all self-relative
  119. on the PPC so that calls to any particular word will have a different
  120. bit pattern depending on where they are.
  121.  
  122. class_h is $BC1D, and will give an error if we try to EXECUTE a class
  123. (as with all $BCxx codes).  I doubt this will break any existing code.
  124.  
  125. Note also we've moved the "flags" from after the indexed width item,
  126. up to be the first item.  This is so the 4-byte items come out aligned
  127. without sundry padding.
  128.  
  129.  
  130.         ==============  ivar dictionary entry  ================
  131.  
  132. ¥ note: this format is the same on the PPC and 68k, for once!
  133.  
  134. 4 bytes        hashed name
  135. 4 bytes        link to prev ivar dic entry (self-relative addr)
  136. 4 bytes        class pointer (relocatable)
  137. 2 bytes        offset of this ivar's data from the base addr of the class
  138. 2 bytes        number of elements if indexed, or zero if not
  139. 2 bytes        flags
  140.  
  141. Flag bits: (zero is rightmost - what will we do on PowerPC?)
  142.  
  143.     $0001    ivar gets an object header
  144.     $0002    this is a static ivar
  145.     $0004    this is a public ivar
  146.  
  147. Note: although indexed objects can have 2^^32 elements, we are
  148. assuming that an ivar can't have more than 64K elements.  This is
  149. because we are limiting the maximum ivar length of a class to 64K bytes,
  150. which is a stricter condition.  Would anybody want a longer ivar than
  151. this??
  152.  
  153.         ==============  Method dictionary entry  ================
  154.  
  155. 4 bytes        hashed name
  156. 4 bytes        link to prev method dic entry (self-relative addr)
  157. 2 bytes        method flags
  158. 2 bytes        0 (alignment)
  159. 2 bytes        $BE40 - "handler code" - not actually used as a handler, but
  160.             marks this as a method for decompiler etc.  Note that an
  161.             inline method uses the code BD40, so I can just look for
  162.             40 in the low byte to see if it's a method.
  163. 2 bytes        flag bytes as for colon defns, giving number of named parms etc.
  164.             This is the method's cfa (xt) here.
  165.  
  166.     (method code follows)
  167.  
  168.  
  169. Method flag bits:
  170.  
  171.     $0001    private method (note other way round to ivars - we're using
  172.             1 for the unusual case)
  173.     $0080    there's a callFirst and/or callLast method
  174.  
  175. Note that the method code starts 6 bytes later than in the 68k version.
  176.  
  177.  
  178.         ==========================================================
  179. *)
  180.  
  181. 34    constant    IFA_offset
  182.  
  183. : ]C    true  -> cstate ;        immediate
  184. : C[    false -> cstate ;        immediate
  185.  
  186. ¥ these are defined in qpClass:
  187.  
  188. ¥    0    value    PUB/PRIV    ¥ -1 private, 1 public, 0 default - for ivars and methods
  189. ¥ false    value    STATIC?        ¥ true if following ivars are to be static
  190. ¥    0    value    ^COMP_CLASS    ¥ addr of the class we're currently compiling
  191. ¥    0    value    PIVAR        ¥ hashed name of any public ivar we're accessing
  192. ¥    0    value    PIVSEL        ¥ hashed selector of any msg being sent to
  193.                             ¥  to a public ivar
  194.  
  195. ¥    0    value    NEWOBJECT    ¥ addr of object being created
  196. ¥    0    value    #SUP        ¥ number of superclasses for current class
  197. ¥    0    value    SUPERS_TO_SKIP
  198. ¥    0    value    INITID
  199.  
  200.  
  201.     0    value    thisM
  202.     0    value    superM
  203.     0    value    tempObjs    ¥ gets addr of class Dummy which we use for temp objects
  204.  
  205.  
  206. ¥                ===============================
  207. ¥                        UTILITY WORDS
  208. ¥                ===============================
  209.  
  210. : PRIVATE        -1 -> pub/priv  ;        ¥ following methods and ivars will be private
  211. : PUBLIC         1 -> pub/priv  ;        ¥ following methods and ivars will be public
  212.  
  213. : END_PRIVATE    0 -> pub/priv  ;        ¥ back to the default
  214. : END_PUBLIC    0 -> pub/priv  ;        ¥ ditto
  215.  
  216.  
  217. ¥ TOfind looks for a temp (local) object.
  218.  
  219. : TOfind  { str-addr -- ^ivar offs T | -- str-addr F  }
  220.     str-addr
  221.     tempObj_framesize  NIF  false  EXIT  THEN    ¥ out if no temp objects
  222.     hash
  223.     tempObjs <findIV>
  224.     IF                    ¥ ( -- ^ivar offs xdispl-offs )
  225.             drop        ¥ xdispl-offs must be zero for class Dummy
  226.             dup $ FFFE >=
  227.             IF            ¥ self or super - mustn't match these in class Dummy!
  228.                 2drop  str-addr false  EXIT
  229.             THEN
  230.             true
  231.     ELSE    str-addr false
  232.     THEN
  233. ;
  234.  
  235. (*
  236. LocFind will be called from Ufind, which is the vector that gets first
  237. shot at recognizing a word.
  238. It looks at all the possibilities involving local names, which are
  239. not in the regular dictionary.  These possibilities are: named parms/locals,
  240. local objects, and if a class is being compiled, ivars of this class.
  241.  
  242. In the latter case, we arrange for the ivar's address to
  243. be pushed at run time simply by compiling ^base followed by an add of the
  244. ivar's offset - our code generation will produce optimal code for this.
  245. We then have to return the xt of some word to keep FIND happy - we don't
  246. need to compile anything else, so we use the xt of NULL and return a 1
  247. instead of True - this makes FIND think it's immediate.  So NULL is
  248. executed immediately, which does precisely nothing.
  249.  
  250. The one exception to this is if the "ivar" turns out to be SELF or SUPER
  251. - in this case we need to call the nucleus word SELF which works out
  252. the right base address (this is what happened pre-2.5).  Here we keep
  253. FIND happy by pushing the xt of SELF and True, so that it sees we've
  254. found SELF.
  255. *)
  256.  
  257. : LocFind        ¥ ( str-addr -- cfa T  |  -- str-addr F )
  258.     Pfind    ?dup  ?EXIT                ¥ Found a named parm/local
  259.     TOfind
  260.     IF                                ¥ Found temp obj
  261.         nip                            ¥ Don't need its dic addr
  262.         postpone locReg  postpone literal  postpone +
  263.         ['] null  1  EXIT
  264.     THEN
  265.  
  266. ¥ Now we look for an ivar name
  267.  
  268.     cstate  NIF  false  EXIT  THEN        ¥ search fails if we're not compiling
  269.                                         ¥  a class
  270.     dup hash ^comp_class IFA_offset false  (findM)
  271.     IF                                    ¥ Found ivar
  272.         nip nip                            ¥ don't need embedded obj offs or
  273.                                         ¥  string addr
  274.         12 + w@                            ¥ ivar offset
  275.         dup $ FFFE >=                    ¥ is it SELF or SUPER (just used in
  276.                                         ¥  isolation)?
  277.         IF    drop  
  278.             " (^base) 4- dup w@x + 8 +" evaluate        ¥ i.e. SELF - but I can't evaluate
  279.                                                         ¥  that, or we'll end up here again
  280.                                                         ¥  and infinitely recurse!
  281.         ELSE
  282.             postpone (^base) postpone literal  postpone +
  283.         THEN
  284.         ['] null  1
  285.     ELSE    false
  286.     THEN  ;
  287.  
  288.  
  289. ¥ 0 -> quitvec   0 -> abortvec   0 -> objInit        ¥ clear vectors
  290. ¥ ' pfind  -> ufind
  291.  
  292. ¥ in qpClass
  293. ¥ : ?CLASS        ¥ Error if not compiling a class definition.
  294. ¥     cstate 0=  ?error 115  ;
  295.  
  296.  
  297. ¥                        ========================
  298. ¥                                BINDING
  299. ¥                        ========================
  300.  
  301.     0    value    OBJ_BASE
  302.     0    value    OBJ_DISPL
  303.     0    value    OBJ_LOCAL_DISPL
  304.     0    value    OBJ_IND
  305.  
  306. false    value    SELF?
  307.  
  308.  
  309. (*    Note: I think our obj_ind value might become obsolete on the PPC, since
  310.     we don't now use an indirect count in an OD, but just do repeated fetches
  311.     to different registers till we come to the data we want.
  312.     On the 68k, as far as I can tell, the only time obj_ind wasn't zero was
  313.     when we did an early bind to an addr on the stack, or to an objPtr (which
  314.     used the same code).  This was also the reason we kept two offsets
  315.     - obj_displ and obj_local_displ.  Obj_displ applied before any indirection
  316.     steps, and obj_local_displ after.  I think on the PPC these complexities
  317.     might be able to go away.
  318. *)
  319.  
  320.  
  321. : (OBJ)        ¥ Called from within an inline method.  Passes the object's
  322.             ¥  base and displacement to Handlers to generate the correct
  323.             ¥  address.  Optimization will then apply.
  324.  
  325.     obj_base obj_displ
  326.     obj_ind  genaddr
  327.     obj_local_displ  postpone literal  postpone +  ;
  328.  
  329.  
  330. : (IX)
  331.  
  332.     (*    Called from within an inline method.  Compiles code to generate
  333.         the indexed address.
  334.         ^comp_class has been set by inl_bind to the class of the obj
  335.         we're binding to.  One tricky point is that to access the indexed
  336.         area, we have to use the dlen value in this class, not the class
  337.         of the method we're calling (which may be a superclass).  But
  338.         the obj_local_displ has already had the embedded object offset
  339.         added in (if any).  We have to ignore this, since we're using 
  340.         the object's class, not the method's.  When the method was found,
  341.         the value emb_obj_offs was set to this offset, so we subtract
  342.         it here.
  343.     *)
  344.  
  345.     ^comp_class dlen&xwid  swap
  346.     self?
  347.     IF  drop  -1  ELSE  #off-align  6 +  THEN
  348.     obj_base obj_displ obj_local_displ
  349.     emb_obj_offs -
  350.     obj_ind  ^comp_class ffa w@
  351.     genxaddr  ;
  352.  
  353.  
  354. : ^BASE
  355.     compinline?
  356.     IF        (obj)
  357.     ELSE    postpone (^base)
  358.     THEN  ;            immediate
  359.  
  360.  
  361. : ^ELEM
  362.     compinline?
  363.     IF        (ix)
  364.     ELSE    " (^elem)"  evaluate            ¥ need PPC version
  365.     THEN  ;            immediate
  366.  
  367.  
  368. : OBJ    postpone ^base  ;    immediate        ¥ for backward compatibility
  369. : IX    postpone ^elem  ;    immediate        ¥ ditto
  370.  
  371.  
  372. forward enter_meth_in_mod
  373.  
  374. local  EARLY_BIND  { oCfa oBase oDispl oLDispl oind slf? ¥ ^mod ptr -- }
  375.  
  376.  
  377. : INL_BIND    ¥ ( -- b )
  378.     ^comp_class  cstate  self?                    ¥ Save over upcoming evaluate
  379.     slf? NIF  objClass -> ^comp_class  THEN        ¥ Set ^comp_class and cstate
  380.     true -> cstate                                ¥  so ivars are accessible
  381.     slf? -> self?
  382.     oCfa  inline_h
  383.     -> self?  -> cstate  -> ^comp_class            ¥ Restore
  384. ;
  385.  
  386.  
  387. : MODULE_BIND
  388.     heldMod  dup
  389.     @ @            ¥ get mod handle and dereference - addr of mod start
  390.     -> ^mod
  391.     ^mod 8 + -> ptr            ¥ self-rel addr of exports table
  392.     ptr @ ++> ptr            ¥ ptr -> start of table
  393.     0 -> methIndex
  394.     BEGIN
  395.         ptr @ dup 0<
  396.         IF            ¥ we have a problem - we didn't find the entry in the
  397.                     ¥  module's export table, though it ought to be there!
  398.                     ¥ Maybe heldMod should have been zero, and we shouldn't
  399.                     ¥  have been trying to do a module bind at all??
  400.             cr cr ." heldMod " heldMod .h  cr cr
  401.             heldMod 32 - 64 dump
  402.             198 die        ¥ "internal error"
  403.         THEN
  404.         ^mod +  oCfa =
  405.     NWHILE
  406.         4 ++> methIndex  4 ++> ptr
  407.     REPEAT
  408.     
  409. ¥ methIndex now has the export table offset for the method.
  410.     (obj)                        ¥ compile push of obj addr (clears heldMod!)
  411.  ( heldMod )  lit_addr            ¥ and a push of the module's addr
  412.     methIndex  postpone literal    ¥ and a push of export table offset
  413.     ['] enter_meth_in_mod  call_h
  414. ;
  415.  
  416.  
  417. : NORM_BIND
  418.     heldMod
  419.     IF      module_bind
  420.     ELSE    oCfa  (obj)  call_h        ¥ call_h will see by the handler code
  421.     THEN                            ¥  that this is a method, and do the
  422. ;                                    ¥  right things, hopefully
  423.  
  424. :loc  EARLY_BIND        ¥ { oCfa oBase oDispl oLDispl oind slf? -- }
  425.     obj_base  obj_displ  obj_local_displ  obj_ind        ¥ Save
  426.     oBase    -> obj_base            oDispl    -> obj_displ
  427.     OLdispl    -> obj_local_displ    oind    -> obj_ind
  428.     oCfa 2- w@  $ BD40 =
  429.     IF      inl_bind
  430.     ELSE    norm_bind
  431.     THEN
  432.  
  433.     -> obj_ind  -> obj_local_displ
  434.     -> obj_displ  -> obj_base            ¥ Restore
  435. ;loc
  436.  
  437.  
  438. : BIND_TO_OBJ  { cfa ^obj offs -- }
  439.     cfa
  440.     -1                    ¥ -1 as "base" signals handlers to generate
  441.     ^obj                ¥  a normal dic addr.  We still carry the
  442.                         ¥  offs here since if we need to access the
  443.                         ¥  indexed area, we want the original obj addr,
  444.                         ¥  not some embedded object.
  445.     offs  0  false  early_bind  ;
  446.  
  447. : BIND_TO_STK  { xt ¥ svHeldMod -- }
  448.     heldMod -> svHeldMod  0 -> heldMod
  449.     xt hStkObj            ¥ ( -- xt base displ )
  450.     svHeldMod -> heldMod
  451.     0  0  false  early_bind  ;
  452.  
  453. : BIND_TO_IVAR  { cfa offs -- }
  454.     cfa  obj_base  obj_displ
  455.     obj_local_displ offs +
  456.     obj_ind  false  early_bind  ;
  457.  
  458. : BIND_TO_TMPOBJ  { cfa offs -- }
  459.     cfa
  460.     <'> locReg 3+ c@        ¥ current locReg number
  461.     offs
  462.     0 0 false  early_bind  ;
  463.  
  464. : BIND_TO_SELF  { cfa offs -- }
  465.     cfa  obj_base  obj_displ  offs  obj_ind  true  early_bind  ;
  466.  
  467.  
  468. ¥                    ============================
  469. ¥                            :CLASS  etc.
  470. ¥                    ============================
  471.  
  472. (*
  473. Here we set up some quantities so that we can send messages to SELF
  474. or SUPER.  These are treated syntactically as ivars, so to implement
  475. them we actually set up dummy ivars SELF and SUPER.
  476.  
  477. When we're processing a :CLASS definition, we plug the appropriate
  478. addresses into these ivars.  ^SELF is a word defined to return the
  479. addr of the dummy ivar SELF, so we can do the plugging.
  480. In the case of SUPER, there may be several superclasses, so we have
  481. to go through a class descriptor, since that's the only place we look
  482. for an n-way (a set of addresses).  So we set the "class" of SUPER
  483. to a dummy class SUPCL, which has no ivars or methods (so the search
  484. will pass right on by), and plug the superclass pointer of SUPCL to
  485. point to the current n-way for the superclasses of the class we're
  486. defining.
  487. *)
  488.  
  489.  
  490. ¥ : ^SELF        self_vbl  displace  ;
  491.  
  492.  
  493.  
  494. : :CLASS
  495.     ?exec  header  $ BC1D codeW,
  496.     CDP -> ^comp_class
  497.     0 -> pub/priv  0 -> #1st  0 -> #last
  498.     false -> rec?  false -> union?  false -> static?
  499.     307
  500. ;        immediate
  501.  
  502.  
  503. : MERGE_INFO  { ^sup ivlen ¥ ^wid wid prevWid -- dlen }
  504.     ^sup dlen&xwid  -> wid        ¥ indexed width of this superclass
  505.     ^sup ffa 1+ c@ 5 and        ¥ Merge "general" and "indexed" flags with
  506.     ^comp_class ffa 1+  cset            ¥  what we have already
  507.     wid  0EXIT                    ¥ If this superclass not indexed, we're done
  508.     
  509. ¥ This class is indexed - we need to check if prev classes were indexed
  510. ¥  and make sure the widths are compatible.
  511.  
  512.     ^comp_class dfa 2+  -> ^wid        ¥ Addr of wid field in class we're building
  513.     ^wid w@  -> prevWid            ¥ Get previous width
  514.     wid 32760 u>                ¥ "indexed width" of 32766/7 really means
  515.     IF                            ¥  obj_array.
  516.         prevWid                    ¥ In this case if we already have a width,
  517.         IF        prevWid -> wid    ¥  we use that,
  518.         ELSE    wid
  519.                 ivlen  -> wid    ¥ otherwise current ivar len becomes the width.
  520.  
  521.             ( old wid ) 32766 =
  522.                 IF        ¥ large_obj_array - mark boundary between ivars
  523.                         ¥  we are/aren't mapping to the indexed area
  524.                     ivlen aligned  ^comp_class xoffa w!
  525.                     wid aligned 4+  -> wid    ¥ and allow for ^class offset
  526.                                             ¥  and indexed area offset
  527.                                             ¥  before each element
  528.                 THEN
  529.         THEN
  530.     THEN
  531.     prevWid
  532.     NIF     wid  ^wid w!        ¥ If no prev width, set width & we're done
  533.     ELSE    prevWid wid <>  ?error 88        ¥ "Incompatible indexed widths"
  534.     THEN
  535. ;
  536.  
  537.  
  538. local    (SUP)   { ¥ ^supcl ivlen ^nway ^sup ^newClass thisLen -- }
  539.  
  540. : NEXT_SUPER    ( cfa -- )
  541.     chkClass  -> ^sup
  542.     ^sup relocCode,                    ¥ Add ^class to n-way
  543.     ^sup ivlen merge_info   -> thisLen
  544.     #sup IF                            ¥ If this is a subsequent class,
  545.         ivlen #align4  4+  -> ivlen    ¥  align and allow for ^class offset and
  546.                                     ¥  2 extra bytes padding
  547.     THEN
  548.     thisLen ++> ivlen                ¥ And add ivar length of new class
  549.     1 ++> #sup  ;
  550.  
  551.  
  552. : SUPERS_LOOP
  553.     BEGIN                        ¥ Loop over superclasses:
  554.         '                        ¥ cfa of next item on list
  555.         }or)? IF  drop  EXIT  THEN
  556.         ( cfa )  next_super            ¥ handle next superclass
  557. ¥        1super?  ?EXIT                ¥ Yerk has only one superclass
  558.     AGAIN  ;
  559.  
  560.  
  561. :loc  (SUP)
  562.     307 ?pairs                        ¥ Make sure we're in the right place
  563.     CDP -> ^newClass
  564.     46 ( classSize )  code_reserve            ¥ Space for class record
  565.     CDP -> ^nway                    ¥ n-way for superclasses will
  566.     0 -> ivlen  0 -> #sup            ¥  start here
  567.     ^newClass 2+ 32 bounds
  568.     DO  ^nway  i displ!  4 +LOOP    ¥ point methods links to nway
  569.     ^nway ^newClass IFA  displ!        ¥ and ivars link
  570.     false -> relocChk?
  571.     supers_loop                        ¥ Loop over superclasses
  572.     0 code,                            ¥ Terminate n-way
  573.     " SUPCL" sFind drop -> ^supcl
  574.     ^supcl 2+ 32 bounds
  575.     DO  ^nway  i displ!  4 +LOOP    ¥ we point the method and ivar links
  576.     ^nway                            ¥  in supcl to the n-way
  577.     ^supcl IFA  displ!
  578.  
  579.     ^comp_class xoffa w@
  580.     " SUPCL" sFind drop xoffa w!    ¥ and set xoffs in supCl
  581.  
  582.     ivlen ^comp_class dfa w!        ¥ Set total ivar length
  583. ¥    ^comp_class  ^self 8 +  reloc!    ¥ Store ^class in SELF
  584.     true -> relocChk?
  585.     postpone ]c                        ¥ In a class definition
  586.     308
  587. ;loc
  588.  
  589.  
  590. : SUPER{        ( false -> 1super? )   (sup)  ;        immediate
  591.  
  592. ¥ : SUPER(        postpone super{  ;                immediate
  593.  
  594. ¥ : <SUPER    true -> 1super?  (sup)    ;            immediate
  595.             ¥ For compatibility with Yerk -- only looks for 1 superclass
  596.  
  597.  
  598. : (;CL)
  599.     postpone [  postpone c[
  600. ;
  601.  
  602.  
  603. : ;CLASS
  604.     (;cl)  308 ?defn  ;            immediate
  605.  
  606.  
  607.    1    value    DFRSELID    ¥ 1 means no late bind going on - otherwise it's
  608.                                ¥  the selector we're late binding with
  609. true    value    SLCTRS?        ¥ Set false to treat selectors as normal words
  610.                             ¥  for full ANSI compatibility
  611.  
  612. : SEL?        ¥ ( addr -- addr b )  True if word at addr is a selector xxx:
  613.     slctrs?  NIF  false  EXIT  THEN
  614.     dup  count tuck  1- + c@  & :  =
  615.     swap 1 >  and  ;
  616.  
  617.  
  618. : GETSELECT            ¥ Gets a selector from the input stream
  619.     mword
  620.     sel?  not ?error 124
  621.     hash
  622.     1 -> dfrSelID  ;
  623.  
  624.  
  625. ' null    vect    GET1ST&LAST
  626. ' null    vect    DoCall1ST
  627. ' null    vect    DoCallLast
  628.  
  629.  
  630. : M_HEADER  { selID -- }    ¥ Builds a method header and entry sequence.
  631.                             ¥ Note: also called from the assembler.
  632.     selID ^comp_class MFA  selID  hashed-hdr    ¥ Build header
  633.     drop                            ¥ drop extra selID (needed by MFA)
  634.     CDP 4-  -> ^meth_link
  635.     pub/priv -1 =  1 and  codeW,    ¥ public/private flag (default is public)
  636.     0 codeW,                        ¥ padding for alignment
  637.     $ BE400000 code,                ¥ "handler code" for PPC methods,
  638.                                     ¥  and initial flag bytes
  639.     CDP 2- -> thisM                    ¥ Remember method cfa
  640. ;
  641.  
  642. ¥    0 codeW,                        ¥ space for parm flags (or do it in Mentry?)
  643. ¥    Mentry  ;                        ¥ Compile the entry sequence
  644.  
  645.  
  646. : :M { ¥ selID -- }            ¥ Starts compiling a method.
  647.  
  648.     CDP -> last_colon_defn            ¥ used by compile_call in checking where
  649.                                     ¥  a call is coming from
  650.     true -> method?
  651.     ?class
  652.     rec? ?error 191                    ¥ unmatched '{' in ivar list
  653.     0 -> superM
  654.     getSelect -> selID
  655.     10 -> cstate                    ¥ Means we've read :m, no call_1st yet
  656.  
  657.     selID ^comp_class MFA_offset true (findm)        ¥ is method already defined?
  658.     IF
  659.         -> superM
  660. ¥        warnings?
  661. ¥        IF    cr  CDP count type type# 182         ¥ "Method redefined"
  662. ¥        THEN
  663.         heldMod 
  664.         NIF  superM ^comp_class > ?error 183  THEN
  665.                                             ¥ - but if in same class, error
  666.         drop
  667.     THEN
  668.  
  669.     get1st&last  ¥ ?unHoldMod
  670.     CDP -> const_data_start
  671.     selID m_header                    ¥ Build method header
  672.     #1st #last +
  673.     IF  $ 80  thisM 5 - cset  THEN    ¥ set call1st/callLast flag
  674.     obj_base_reg -> obj_base        ¥ gpr20
  675.     0 -> obj_displ                    ¥ For any inline method calls
  676.     false ppc_entry                    ¥ Start to compile the method
  677.     drop 305                        ¥ change security marker to say method
  678.     doCall1st                        ¥ Compile any Call1st calls first
  679. ;        immediate
  680.  
  681. : ;M
  682.     true -> method?                ¥ things might have happened during the defn
  683.                                 ¥  to make it false, like compilation being
  684.                                 ¥  turned off and on.  This doesn't matter,
  685.                                 ¥  but we definitely need it true here.
  686.     #last IF  doCallLast  THEN
  687.     curr-def 2-  (;)
  688.     0 -> #1st  0 -> #last
  689.     305 ?defn  ;        immediate
  690.  
  691.  
  692. ¥    ============== Local sections for methods ==============
  693.  
  694. ¥ These function just like regular local sections.  The implementation
  695. ¥ is nearly the same.
  696.  
  697.     0    value    mloc_addr
  698.  
  699. : MLOCAL        ¥ Starts a local section for methods
  700.     local?  ?error 93  1 -> local?        ¥ We change it to the normal -1
  701.                                         ¥ as soon as "{" is read.
  702.     CDP -> CD_gpr_loc
  703.     postpone :m  drop
  704.     postpone [
  705.     CDP -> mloc_addr
  706.     $ 48000000  code,        ¥ uncond branch to be resolved by :mloc
  707.     private
  708. ;
  709.  
  710.  
  711. : :MLOC
  712.     public  ?loc  getSelect drop
  713.     CDP -> const_data_start
  714.     $ BE030000  code,            ¥ marks this as the :mloc position
  715.                                 ¥  (just for disassembly)
  716.     true -> method?
  717.     false -> local?                ¥ so entry sequence gets compiled
  718.     true -> mloc?                ¥ so const data gets handled properly
  719.     false ppc_entry                ¥ handle ppc proc entry
  720.     drop 309                    ¥ security marker for :mloc
  721.     curr-def
  722.       mloc_addr -> curr-def
  723.       PLentry
  724.     -> curr-def
  725.     tempObj_framesize IF  initTemps  THEN
  726. ;        immediate
  727.  
  728.  
  729. : ;MLOC
  730.     309 ?defn
  731.     false -> leaf?            ¥ let's just reduce the bug possibilities!
  732.     #last IF  doCallLast  THEN
  733.     mloc_addr 2-  (;)
  734. ¥    #last  IF  true -> method?  doCallLast  ( defnEnd)  false -> method?  THEN
  735.     0 -> #1st  0 -> #last
  736.     curr-def mloc_addr -    ¥ finally we resolve the forward branch
  737.     mloc_addr +!            ¥   from MLOCAL
  738. ;            immediate
  739.  
  740.  
  741. ¥    ================   INDEXED, GENERAL etc.   =================
  742.  
  743. ¥ These are words which can appear in a class declaration, in the
  744. ¥ position
  745.  
  746. ¥  :class someClass super{ someSuper }   general
  747.  
  748. ¥ They add attributes to the class.
  749.  
  750. : INDEXED        ¥ ( width -- )  Sets a class and its subclasses to indexed
  751.     ?class  ^comp_class dfa 2+  w!  ;
  752.  
  753. : LARGE  ;        ¥ in effect, this always applies on the PPC
  754.  
  755.  
  756. : GENERAL
  757.  
  758. (*    Sets the "general" option on a class, which will force an ivar of that class
  759.     to be a general object with a class pointer (so it can be late-bound to) even
  760.     if it's within a record.  Normally you should just not put such ivars in a
  761.     record, but using GENERAL gives a bit of extra security, for classes for which
  762.     you know that they will definitely be late-bound to.  (An attempt to late-bind
  763.     to an ivar without a class pointer will give the "not an object" error at run
  764.     time, which isn't easy to track down.)
  765.     Note that indexed classes are always general anyway.  Also if there's a message
  766.     sent to [self] somewhere in one of the methods, we know that the class *must*
  767.     be general, so in this case we simply set the general attribute.
  768. *)
  769.     ?class  ^comp_class ffa 1+ dup c@ 4 or  swap c!  ;
  770.  
  771.  
  772. ¥                    ===========================
  773. ¥                            SELECTORS
  774. ¥                    ===========================
  775.  
  776. ¥ First, here are the special-purpose things which can follow a selector.
  777. ¥ These can't appear in isolation.
  778.  
  779. ¥ We allow ** and [] as synonyms of [ ] to late-bind to whatever is on the
  780. ¥ stack.  Note:  [] is used in JForth.
  781.  
  782. ¥ We also allow [self] as a synonym of [ self ]
  783.  
  784. : **        83 die  ;        ¥ "Has no meaning unless preceded by a selector"
  785. : []        83 die  ;
  786. : [SELF]    83 die  ;
  787. : SUPER>    83 die  ;
  788. : IVAR>        83 die  ;
  789. : CLASS_AS>    83 die    ;
  790.  
  791.  
  792. : ]
  793.     hide  dfrSelID  1 = IF   postpone ]  EXIT  THEN        ¥ if no late bind, this is a
  794.                                                         ¥  standard Forth ]
  795.     dfrSelID NIF  187 die  THEN        ¥ late bound public ivar reference
  796.                                     ¥  not implemented yet!
  797.     state
  798.     IF        251 ?pairs  dfrSelID  postpone literal
  799.             postpone send
  800.     ELSE    $ deadbeef $ 106 db        ¥ shouldn't happen
  801.             dfrSelID  send
  802.     THEN
  803.     1 -> dfrSelID  ;        immediate
  804.  
  805.  
  806. 100        constant    pubIvarTyp        ¥ &&& temp
  807. false    value        need_class?
  808.  
  809. false    value        implicit_late_bind?        ¥ true for pre-2.7 auto-late-bind
  810.                                             ¥  to locals or values
  811.  
  812. (* REFTOKEN ( -- cfa tokenType | -- various type )
  813.    is called when we've parsed a selector - it determines the type of the
  814.    following word.
  815.    
  816.    The order of checking determines the priority of names.  Up to 2.6 we
  817.    checked for locals first, but this was a bad idea since a local could
  818.    have the same name as an object, and implicit late binding to locals
  819.    was legal.  This wouldn't show up until a crash at run time.  So now we
  820.    check for temp objects, then ivars, then locals IF implcit_late_bind? is
  821.    true.
  822.  
  823.    "various" will be the cfa of whatever came after the selector, or
  824.    ( offset ^ivar ) for ivars and temp objects (which are treated as ivars
  825.    of the class Dummy).
  826. *)
  827.  
  828. : REFTOKEN        ¥ ( -- cfa tokenType | -- various type )
  829.  
  830.     false -> need_class?
  831.     Mword                                    ¥ grab next word
  832.     TOfind    IF  tmpObjTyp    EXIT  THEN        ¥ check for temp object
  833.     IVfind    IF  ivarTyp        EXIT  THEN        ¥ check for ivar
  834.     
  835.     implicit_late_bind?
  836.     IF    Pfind    IF  locTyp    EXIT  THEN        ¥ check for named parm/locals
  837.     THEN
  838.  
  839.     ( here )  dup thread dup @ +  (find)  0=  ?error 125
  840.     dup ['] **            =  IF  lbTyp                            EXIT  THEN
  841.     dup ['] []            =  IF  lbTyp                            EXIT  THEN
  842.     dup ['] [            =  IF  bktTyp                            EXIT  THEN
  843.     dup ['] [self]        =  IF  lbSelfTyp                        EXIT  THEN
  844.     dup ['] super>        =  IF  superTyp                            EXIT  THEN
  845.     dup ['] ivar>        =  IF  pubIvarTyp                        EXIT  THEN
  846.     dup ['] class_as>    =  IF  true -> need_class?  classTyp    EXIT  THEN
  847.     dup hdlr
  848.     CASE
  849.         $ BC0B        OF    >obj  objTyp    ENDOF
  850.         $ BC1D        OF    classTyp        ENDOF
  851.         $ BC1F        OF    objPtrTyp        ENDOF
  852.         $ BC03        OF    valTyp            ENDOF
  853.                                 ¥ Note: here we can treat vectors as words.
  854.  
  855.         126 die                    ¥ "Not an object name"
  856.     ENDCASE
  857.  
  858. ¥ but if we got wordTyp or valTyp, it's only legal if implicit_late_bind?
  859. ¥  is true
  860.     implicit_late_bind?  ?EXIT        ¥ all OK - done
  861.     dup wordTyp =  over valTyp =  or
  862.     IF  126 die  THEN
  863. ;
  864.  
  865.  
  866. ¥ These words handle the binding of a selector to whatever follows it.
  867.  
  868. (*    FIX_PIVAR does the housekeeping for accessing a public ivar.  When we
  869.     encounter  msg: ivar>  then we store the selector in pivSel, and the
  870.     hashed ivar name in pivar.  We then continue with a zero "selector",
  871.     which signals that it's a public ivar access, and leads to us being
  872.     called back here to fix everything up once we've got the class.
  873. *)
  874.  
  875. : FIX_PIVAR  { ^class in_class? ¥ ^ivar offs xdispl-offs -- cfa offs xdispl-offs }
  876.  
  877.     ^class ?>classInMod -> ^class
  878.  
  879.     pivar ^class <findIV>            ¥ ( ^ivar offs xdispl-offs true  OR  false )
  880.     0= ?error 192                    ¥ "ivar not found"
  881.     -> xdispl-offs  -> offs  -> ^ivar
  882.     ^ivar iffa w@                     ¥ get ivar flags
  883.     dup 4 and 0=    ?error 193        ¥ ivar not public
  884.     2 and                            ¥ static flag
  885.     in_class?
  886.     IF        0=  ?error 197            ¥ ivar not static
  887.     ELSE    ?error 195                ¥ wrong syntax for public static ivar
  888.     THEN
  889.  
  890. ¥ now we find the method in the ivar's class
  891.  
  892.     pivSel ^ivar  ivFindM drop        ¥ %%% don't worry about large_obj_arrays
  893.                                     ¥  which are ivars yet!
  894.   ( cfa  offs-within-ivar )
  895.     in_class?
  896.     IF            ¥ for public static ivars, the "offset" we return is
  897.                 ¥  actually the ivar's real data address.
  898.         drop ^ivar  static_ivar_offs +  @abs  -> offs
  899.     ELSE
  900.         ++> offs
  901.      THEN
  902.      offs  xdispl-offs
  903. ;
  904.  
  905.  
  906. ¥ PUBLIC_STATIC_IVAR_REF handles a message bind to a public static ivar
  907. ¥ (done via the  msg: ivar> in_class someClass  syntax)
  908.  
  909. : PUBLIC_STATIC_IVAR_REF
  910.     refToken
  911.     classTyp <>  ?error 196            ¥ class name must follow in_class
  912.     true  fix_pivar drop            ¥ %%% don't worry about large_obj_arrays
  913.                                     ¥  which are public static ivars yet!
  914.     0  bind_to_obj
  915. ;
  916.  
  917.  
  918. ¥ OBJREF handles a reference to a normal object.
  919.  
  920. : OBJREF  { selID ^obj ¥ cfa offs xdispl-offs -- }
  921.     selID
  922.     IF    selID ^obj  objFindm
  923.     ELSE                ¥ it's a public ivar reference in the referenced object
  924.         ^obj >class  false  fix_pivar
  925.     THEN
  926.  
  927.   ( cfa offs xdispl-offs )  -> xdispl-offs  -> offs  -> cfa
  928.  
  929.     xdispl-offs
  930.     IF    
  931.         ^obj xdispl-offs +  lit_addr
  932.         " dup @ +" evaluate
  933.         offs IF                ¥ will normally be zero
  934.                 offs postpone literal
  935.                 " +" evaluate
  936.             THEN
  937.         cfa bind_to_stk  EXIT
  938.     THEN
  939.  
  940.      cfa ^obj offs bind_to_obj
  941. ;
  942.  
  943.  
  944. ¥ IVARREF handles a reference to an ivar.
  945.  
  946. : IVARREF  { selID ^ivar offs xdispl-offs ¥ cfa stat? -- }
  947.  
  948.     heldMod  0 -> heldMod                ¥ save
  949.     offs  $ FFFE >=  -> selfRef?        ¥ if self or super.  Allows private
  950.                                         ¥ methods to be found by (findm)
  951.     selfRef?
  952.     IF  supers_to_skip -> sups2skip        ¥ sups2skip is interrogated by (findm).
  953.                                         ¥  This must only be done if self or
  954.                                         ¥  super is the target.
  955.         0 -> offs                        ¥ "real" offset is zero
  956.     ELSE
  957.         ^ivar iffa w@ 2 and  -> stat?    ¥ static ivar?
  958.     THEN
  959.     selID
  960.     IF    selID ^ivar ivFindM            ¥ %%% don't worry about large_obj_arrays
  961.                                     ¥  which are ivars yet!
  962.         selfRef? IF -> xdispl-offs  ELSE drop THEN
  963.  
  964.         ++> offs                    ¥ add embedded obj base offs to ivar offs
  965.         -> cfa
  966.         0 -> sups2skip  0 -> supers_to_skip
  967.  
  968.         selfRef?
  969.         IF    xdispl-offs
  970.             IF    xdispl-offs postpone literal
  971.                 " ^base + dup @ +"  evaluate
  972.                 cfa  bind_to_stk
  973.             ELSE
  974.                 cfa offs bind_to_self  false -> selfRef?
  975.             THEN
  976.     ¥        ?unholdMod
  977.             -> heldMod   EXIT
  978.         THEN
  979.  
  980.     ELSE                ¥ it's a public ivar reference within the referenced ivar
  981.         ^ivar ^iclass false  fix_pivar drop        ¥ %%% don't worry about large_obj_arrays
  982.                                                 ¥  which are ivars yet!
  983.         ++> offs  -> cfa
  984.     THEN
  985.  
  986.     stat?
  987.     IF    cfa  ^ivar static_ivar_offs + @abs  0  bind_to_obj
  988.     ¥    ?unholdMod  
  989.         -> heldMod  EXIT
  990.     THEN
  991.     
  992.     xdispl-offs
  993.     IF    xdispl-offs postpone literal
  994.         " ^base + dup @ +"  evaluate
  995.         offs IF                        ¥ will normally be zero
  996.                 offs postpone literal  " +" evaluate
  997.             THEN
  998.         cfa  bind_to_stk
  999.     ELSE
  1000.         cfa offs  bind_to_ivar
  1001.     THEN
  1002. ¥    ?unholdMod  
  1003.     -> heldMod
  1004. ;
  1005.  
  1006.  
  1007. ¥ OP/CL is common code factored out of objPtrRef and classRef, which
  1008. ¥ are very similar.
  1009.  
  1010. : OP/CL  { selID ^class ¥ cfa offs xdispl-offs -- }
  1011.  
  1012.     selID
  1013.     IF    selID ^class clFindm
  1014.     ELSE
  1015.         ^class  false  fix_pivar
  1016.     THEN
  1017.     -> xdispl-offs  -> offs  -> cfa
  1018.  
  1019.     xdispl-offs
  1020.     IF    xdispl-offs postpone literal
  1021.         " + dup @ +"  evaluate
  1022.     THEN
  1023.     
  1024.     heldMod                    ¥ save
  1025.     offs postpone literal  " +" evaluate
  1026.     -> heldMod                ¥ restore
  1027.     cfa bind_to_stk
  1028. ;
  1029.  
  1030.  
  1031. ¥ OBJPTRREF handles a reference to an object pointer.
  1032.  
  1033. : OBJPTRREF  { selID OP-cfa ¥ OPclass cfa offs xdispl-offs addr -- }
  1034.     OP-cfa  (comp)                    ¥ Compile a fetch of the OP-cfa,
  1035.                                     ¥  giving ^obj at run time
  1036.     OP-cfa 2+ @abs  -> addr
  1037.     addr 4+ @abs  -> OPclass
  1038.     OPclass  0= ?error 86            ¥ "ObjPtr hasn't had a class specified"
  1039.     OPclass hdlr -90 =
  1040.     IF                                ¥ Class is exported
  1041.         OPclass 6 + wdisplace        ¥ Addr of module
  1042.         compmod =  ?error 84        ¥ It's the module we're compiling -
  1043.                                     ¥  this is a no-no, since the ObjPtr
  1044.                                     ¥  reference will use the OLD module!
  1045.         OPclass  ?>classInMod -> OPclass
  1046.     THEN
  1047.     selID OPclass  OP/cl
  1048. ;
  1049.  
  1050. ¥ CLASSREF handles a reference to a class - this means use the object
  1051. ¥  whose addr is on the stack, but ASSUME it is of the given class
  1052. ¥  and early bind, without checking.
  1053. ¥ The code is very similar to objPtrRef, naturally enough.
  1054.  
  1055. : CLASSREF { selID ^class ¥ cfa offs xdispl-offs -- }
  1056.     need_class? IF  '  chkClass -> ^class  false -> need_class?  THEN
  1057.     selID ^class  OP/cl
  1058. ;
  1059.  
  1060.  
  1061. ¥ TMPOBJREF handles a reference to a temp object.  The temp obj
  1062. ¥  is set up as an ivar of class Dummy.
  1063.  
  1064. : TMPOBJREF  { selID ^ivar offs ¥ svHeldMod cfa xdispl-offs -- }
  1065.     heldMod -> svHeldMod  0 -> heldMod
  1066.     selID
  1067.     IF    selID ^ivar ivFindM
  1068.     ELSE
  1069.         ^ivar 8 + @abs  false  fix_pivar
  1070.     THEN
  1071.     -> xdispl-offs  ++> offs  -> cfa
  1072.  
  1073.     xdispl-offs
  1074.     IF    postpone locReg
  1075.         xdispl-offs postpone literal  postpone +
  1076.         postpone dup postpone @ postpone +
  1077.         offs IF  offs postpone literal  postpone +  THEN    ¥ will normally be zero
  1078.         cfa  bind_to_stk
  1079.     ELSE
  1080.          cfa offs  bind_to_tmpObj
  1081.         svHeldMod -> heldMod
  1082.     THEN
  1083. ;
  1084.  
  1085.  
  1086. ¥ SuperRef handles the  msg: super> someSuper  construct.
  1087.  
  1088. : SUPERREF { selID ¥ ^nway namedClass ^nway' cnt -- }
  1089.     ?class                            ¥ Must be compiling a class
  1090.     '  -> namedClass                ¥ get named class xt
  1091.     ^comp_class sfa -> ^nway
  1092.     ^nway -> ^nway'  0 -> cnt
  1093.     BEGIN
  1094.         ^nway' @ 0= ?error 120            ¥ "superclass" not found
  1095.         ^nway' @abs namedClass =
  1096.     NWHILE
  1097.         1cell ++> ^nway'  1 ++> cnt
  1098.     REPEAT
  1099.     cnt -> supers_to_skip
  1100.     selID
  1101.     " SUPCL" sFind drop 46 +    ¥ careful of hard-coded number here
  1102.     $ FFFE  0  ivarRef            ¥ equivalent to msg: super
  1103. ;
  1104.  
  1105.  
  1106. forward COMPREF
  1107.  
  1108. ¥ PubIvarRef handles the  msg: ivar> someIvar IN someObj  construct, to
  1109. ¥  send a message directly to a public ivar in an object.  At this point
  1110. ¥  we've just read "ivar>".
  1111.  
  1112. : PUBIVARREF  { selID ¥ addr len ^class ^ivar -- }
  1113.     selID -> pivSel                    ¥ save selID being sent to the ivar
  1114.     mword hash  -> pivar            ¥ parse ivar name
  1115.     mword count  -> len  -> addr
  1116.     addr len  " IN" s=
  1117.     IF    0                 ¥ dummy "selID" for compRef (not a legal selector)
  1118.         compRef            ¥ handle whatever object comes after IN.  The
  1119.                         ¥  zero selector signals that a public ivar in the
  1120.                         ¥  indicated object is to be accessed - real selectors
  1121.                         ¥  can't ever be zero.  This will lead to fix_pivar
  1122.                         ¥  being called to complete the job.
  1123.     ELSE
  1124.         addr len " IN_CLASS" s=
  1125.         IF        public_static_ivar_ref
  1126.         ELSE    true ?error 194        ¥ "wrong syntax for public ivar"
  1127.         THEN
  1128.     THEN
  1129. ;
  1130.  
  1131.  
  1132. ¥ LBselfRef handles messages to [self] - i.e. late bound to Self.
  1133.  
  1134. : LBSELFREF  ( selID -- )
  1135.     " self" evaluate  postpone literal        ¥ pushes ^self, then selID
  1136.     postpone send
  1137. ;
  1138.  
  1139.  
  1140. ¥ Now here are the main words which compile the selector bindings.
  1141.  
  1142. ¥ CompRef operates at compile time - it compiles a selector bind.
  1143.  
  1144. :f COMPREF        ¥ ( selID -- )
  1145.  
  1146.     refToken    ¥ ( selID <various> type )
  1147.                 ¥    <various> will be the cfa of whatever came after the selector,
  1148.                 ¥    or ( offset ^ivar ) for ivars and temp objects (which are
  1149.                 ¥    treated as ivars of the class Dummy).
  1150.  
  1151.     CASE
  1152.         objTyp        OF  objRef                            ENDOF
  1153.         ivarTyp        OF    ivarRef                            ENDOF
  1154.         objPtrTyp    OF  objPtrRef                        ENDOF
  1155.         tmpObjTyp    OF  tmpObjRef                        ENDOF
  1156.         classTyp    OF    classRef                        ENDOF
  1157.  
  1158. ¥ These next 3 can only come up if implicit_late_bind? is true:
  1159. ¥        valTyp        OF  compdfr                            ENDOF
  1160. ¥        locTyp        OF  compdfr                            ENDOF
  1161. ¥        wordTyp        OF  compdfr                            ENDOF
  1162.  
  1163.         lbTyp        OF  drop  postpone literal
  1164.                         postpone send                    ENDOF
  1165.         lbSelfTyp    OF  drop  LBselfRef                    ENDOF
  1166.         bktTyp        OF  drop  -> dfrSelID  251            ENDOF
  1167.         superTyp    OF    drop  superRef                    ENDOF
  1168.         pubIvarTyp    OF    drop  pubIvarRef                ENDOF
  1169.  
  1170.         82 die                        ¥ "Selector can't be used on that"
  1171.         
  1172.     ENDCASE  ;f
  1173.  
  1174.  
  1175. (*
  1176. RunRef is the execution mode equivalent - it executes a selector bind.
  1177. We do this simply by compiling it in a buffer then executing it there.
  1178. The code is a bit like EX-GEN (see cg7).
  1179.  
  1180. While we're compiling in the buffer, we save CDP on the return stack,
  1181. then restore it before executing what we compiled (since it might do some
  1182. compiling itself).  This isn't long, but it's a bit tricky:
  1183. *)
  1184.  
  1185. : runRefBuf  ;                            ¥ never called, just ticked
  1186.                 256 code_reserve        ¥ allows 4 nested binds - worst case
  1187.                                         ¥  32 bytes each, we hope
  1188. 0    value        bufPtr
  1189. 0    value        hiCDP
  1190.  
  1191.  
  1192. : RUNREF  { selID ¥ svCDP svBufPtr svState svMC svMD -- }
  1193.  
  1194.     CDP -> svCDP                ¥ save DP
  1195.     CDP hiCDP umax -> hiCDP        ¥ so we can reset CDP to right place on an error
  1196.  
  1197.     bufPtr NIF  ['] runRefBuf 2-  ELSE  bufPtr  THEN
  1198.     dup -> CDP  -> svBufPtr    ¥ now we'll compile in runRefBuf
  1199.     state -> svState        ¥ save state
  1200. ¥    -1 -> state                ¥ need compile state so this compilation works properly
  1201.     :noname  drop            ¥ start a noname defn - drop security flag, leave xt
  1202.     selID compRef            ¥ compile the binding
  1203.     300  postpone ;            ¥ end noname defn, return to interpretation
  1204.     svState -> state        ¥ restore state
  1205.     0 -> hiCDP                ¥ don't need it any more and could cause problems
  1206. ¥    ?unholdMod
  1207.     CDP -> bufPtr            ¥ new bufPtr value
  1208. ¥    svBufPtr  CDP svBufPtr -  fix_caches
  1209.                             ¥ we're about to execute what we just compiled
  1210.     svCDP -> CDP            ¥ restore CDP since the code might compile something
  1211.  
  1212.     modCode -> svMC  modData -> svMD
  1213.     compmod
  1214.     IF    modcode_comp_start half_displ_range +  -> modCode
  1215.         moddata_comp_start half_displ_range +  -> modData
  1216.     THEN
  1217.  
  1218.     ( :noname xt )  execute            ¥ execute compiled code
  1219.  
  1220.     svMC -> modCode  svMD -> modData    ¥ restore module base addr regs
  1221.     svBufPtr -> bufPtr                    ¥ and old bufPtr
  1222. ;
  1223.  
  1224.  
  1225. ¥                ======== Selector support =========
  1226.  
  1227.  
  1228. ¥ MESSAGE is the handling word invoked by using a selector.
  1229.  
  1230. : MESSAGE        immed
  1231.     state
  1232.     IF                      ¥ Compile state
  1233.         compRef                ¥ Compile the message send
  1234. ¥        ?unHoldMod
  1235.     ELSE
  1236.         runRef                ¥ Run state - execute object/vector reference.
  1237.                             ¥ ?unHoldMod is called by ex-method at the
  1238.                             ¥ end, so we don't need to call it here.
  1239.     THEN  ;
  1240.  
  1241.  
  1242. (*
  1243. FIND will call the forward-defined initFind first, to attempt to find
  1244. a name.  So here we re-resolve initFind to lump together all the
  1245. special cases we have to look for after we've parsed an input word,
  1246. but before we can do a regular dictionary lookup.
  1247. At present these are selectors, named parms/locals, ivars
  1248. and local objects.  If we invent more later, they can easily be added.
  1249.  
  1250. If we succeed here, we return the selector ID or zero, the cfa of the 
  1251. handling word, and 1 or -1 (this will cause FIND to exit without doing
  1252. anything more).  If we fail, we return the original string address and
  1253. false.
  1254. *)
  1255.  
  1256. :f initFIND        ¥ ( str-addr -- selID message-cfa T  |  -- str-addr F )
  1257.     sel?                        ¥ is it a selector?
  1258.     IF        hash                ¥ yes - leave selID
  1259.             ['] message  1        ¥  and cfa of message, and 1 (it's immediate)
  1260.     ELSE    LocFind                ¥ no - look for the various kinds of local name
  1261.     THEN  ;f
  1262.  
  1263.  
  1264. ¥ ' 1stFind -> Ufind
  1265.  
  1266.  
  1267. : OBJLEN    ¥ ( -- objlen )  Computes total data length of current object.
  1268.  
  1269.     ^base (^dlen)  dup w@  swap 2+ w@  ?dup
  1270.     IF  idxBase 4- @ 1+  *  + 4+  THEN   ;
  1271.  
  1272.  
  1273.  
  1274. ¥ SET_CLASS should only be used internally in the Mops implementation.  It patches 
  1275. ¥  nucleus objects when their classes are defined in higher-level files.  Actually 
  1276. ¥  it could be used to change the class of any object, but that wouldn't be a very 
  1277. ¥  clever thing to do.
  1278.  
  1279. ¥ Usage:  fFcb  ['] file  set_class
  1280.  
  1281. : SET_CLASS  { ^obj theClass -- }
  1282.     theClass  chkClass  ^obj 8 -  reloc!        ¥ Patch ^class
  1283.     2  ^obj  2-  w!                    ¥ Not indexed (yet)
  1284.     -4 ^obj  4-  w!  ;                ¥ ^class offset
  1285.  
  1286.  
  1287. : CHKSAME        ¥ ( ^obj -- ^obj )
  1288.         ¥ A check that two objects are of exactly the
  1289.         ¥ same class.
  1290.     dup >classXt  ^base >classXt  <> ?error 87  ;
  1291.  
  1292.  
  1293.  
  1294.  
  1295. ¥            ========= Object pointers ==========
  1296.  
  1297. (*    Object pointers are low-level objects (like VALUEs) which point to a
  1298.     normal (high-level) object, and which allow early-bound messages to be
  1299.     sent to the object by syntactically sending them to the object pointer.
  1300.  
  1301.     The normal syntax is
  1302.  
  1303.     ObjPtr  ZZZ    class_is  someClass
  1304.  
  1305.     Thereafter, any messages sent to zzz are early-bound to the object that
  1306.     zzz points to at the time the message executes.
  1307.  
  1308.     If you need to declare the object pointer before the class exists, use
  1309.     SET_TO_CLASS once the class is defined, thus:
  1310.  
  1311.     :class  SOMECLASS    super{ object }
  1312.  
  1313.     ' someOP  set_to_class  someClass
  1314.  
  1315.     etc.
  1316. *)
  1317.  
  1318. : (toOP)  { ^obj OPcfa ¥ OPclass -- }
  1319.  
  1320.     ^obj  nilP =                ¥ If we're storing nil, anything goes
  1321.     check_OP_stores? not or        ¥ Or if checking is turned off
  1322.     NIF    
  1323.         OPcfa 4+ @abs -> OPclass
  1324.         ^obj 8 - @abs OPclass  <>
  1325.         IF                          ¥ Mismatch. We give some useful(?) info.
  1326. ¥            cr  ^obj obj> .id ."  -> "  OPcfa .id
  1327.             87 die
  1328.         THEN
  1329.     THEN
  1330.     ^obj OPcfa !  ;
  1331.  
  1332.  
  1333. :f  ToObjPtr
  1334.     state
  1335.     IF  litAddr_h  " (toOP)" evaluate  ELSE  (toOP)  THEN  ;f
  1336.  
  1337.  
  1338. : CLASS_IS    ¥ ( --< class > )
  1339.     ?exec  '  chkClass  DP 4-  reloc!  ;
  1340.  
  1341.  
  1342. : SET_TO_CLASS  { ^objPtr ¥ ^cl --< class > }
  1343.     to_be_written
  1344. (*
  1345.     '  -> ^cl
  1346.     ^objPtr hdlr -62 <> ?error 85        ¥ "That isn't an ObjPtr"
  1347.  
  1348.             ¥ Now if "class" is an imported word, we change the handler code
  1349.             ¥ to "imported class".  This is normally done when the module
  1350.             ¥ is compiled, but it may not be yet, since we probably
  1351.             ¥ want to refer to the ObjPtr in the module.
  1352.  
  1353.     ^cl hdlr -92 = IF  -90 ^cl 2- w!  ELSE  ^cl chkClass drop  THEN
  1354.     ^cl  ^objPtr 4+  reloc!
  1355. *)
  1356. ;
  1357.  
  1358.  
  1359.  
  1360. ¥        ===================================
  1361.  
  1362. ¥ Bytes is used as the allocation primitive for basic classes
  1363.  
  1364. : BYTES  { numBytes ¥ svRec? -- }
  1365.     ?class
  1366.     rec? -> svRec?  true -> rec?            ¥ Don't want an object header here
  1367.     " object" sFind drop  ivDef
  1368.     numBytes  ^comp_class dfa  w+!
  1369.     svRec? -> rec?  ;
  1370.  
  1371.  
  1372.  
  1373. (*        ================  Temp (local) objects  ===================
  1374.  
  1375. Syntax:
  1376.  
  1377. : aWord  { loc1 loc2 -- }        ¥ Locals are optional, of course
  1378.     temp
  1379.     {    var        v1
  1380.         int        i1
  1381.         string    s
  1382.     }
  1383.  
  1384.  Or you can use temp{ ...  } if you prefer.
  1385.  
  1386. As the syntax is quite similar to a list of ivars of a class, we actually
  1387. implement the temp objects as though they're the ivars of a dummy class
  1388. (which we uncreatively call Dummy).  This is just a convenience during
  1389. the compilation of a defn with temp objects.  It allows us to define them
  1390. and keep them visible during the compilation of the definition, while mainly
  1391. using existing code for ivar access.  We don't need these ivar dic entries
  1392. once the defn is finished, so we actually put them high in the dictionary
  1393. out of the way of the defn we're compiling.  At the end of the defn,
  1394. we reinitialize Dummy's ivar link ready for next time.
  1395. *)
  1396.  
  1397. getSelect release:            constant    releaseID
  1398.  
  1399.  
  1400. :class DUMMY  super{ object }
  1401. ;class
  1402.  
  1403. ' dummy ifa @    constant    dummyIfa
  1404.             ¥ ivar link corresponding to no ivars - it will be a relative
  1405.             ¥  pointer to the n-way for the superclass, and thus a constant
  1406.  
  1407. : RESETTEMPS
  1408.     dummyIfa  ['] dummy ifa  !
  1409.     0  ['] dummy dfa !                ¥ clear dlen and xwid
  1410. ;
  1411.     
  1412.     ¥ Note we don't have to worry about the mfa since Dummy never gets
  1413.     ¥ its own methods.
  1414.  
  1415.  
  1416. (*    InitTemps is called when we're compiling the prologue for a definition
  1417.     with temp objects.  It compiles a call to make_obj for each object, so
  1418.     that they're properly initialized.  Note we can't just call make_obj once
  1419.     using class Dummy, since its ivar list is wiped out after each defn
  1420.     with temp objects, so at run time it won't have any!  But we don't need
  1421.     Dummy at run time anyway - we only need the "ivars" which are the
  1422.     temp objects themselves.
  1423. *)
  1424.  
  1425. :f INITTEMPS  { ¥ infa ^class -- }
  1426.     ['] dummy ifa displace  -> infa
  1427.     BEGIN
  1428.         infa @ 0<
  1429.     WHILE
  1430.         infa ^iclass -> ^class
  1431.         ^class xwid
  1432.         IF        ¥ it's indexed - we'll have #elements on the stack,
  1433.                 ¥  so we need to compile it as a literal for
  1434.                 ¥  make_obj to grab at run time.
  1435.             infa i#els  postpone literal
  1436.         THEN
  1437.         ^class lit_addr
  1438.         infa ioffs  postpone literal
  1439.         postpone locreg  postpone +  postpone make_obj
  1440.         infa ^nextivar  -> infa
  1441.     REPEAT  ;f
  1442.  
  1443.  
  1444. (*    ReleaseTemps is called from (;) in cg5 at the end of a definition.
  1445.     It compiles a release: xxx for all temp objects.  Because of the way
  1446.     we've defined release: in class Object, for simple objects no code will
  1447.     actually be generated.  
  1448.     
  1449.     Note we mustn't call resetTemps here since this might be an EXIT, not
  1450.     the final semicolon.  We leave calling resetTemps till a new temp{ comes
  1451.     up.
  1452. *)
  1453.  
  1454. :f RELEASETEMPS  { ¥ infa -- }
  1455.     ['] dummy ifa displace  -> infa
  1456.     BEGIN
  1457.         infa @ 0<
  1458.     WHILE
  1459.         infa ^iclass  0EXIT            ¥ shouldn't happen, actually
  1460.         releaseID  infa  ivFindM 2drop
  1461.         infa ioffs bind_to_tmpObj        ¥ compile release:
  1462.         infa ^nextivar  -> infa
  1463.     REPEAT
  1464. ;f
  1465.  
  1466.  
  1467. : }TEMP
  1468.     130 ?pairs
  1469.     ['] } >body !                        ¥ restore old action for "}"
  1470.     -> ^comp_class  -> cstate
  1471.     -> curr-def  -> CDP                    ¥ restore other things
  1472.     
  1473. ¥ Now we work out the temp obj framesize.  We have to allow 8 bytes for
  1474. ¥  the header, and an extra 8 in case it's not a method - in cg3 we add
  1475. ¥  16 to RP to get the temp obj pointer whether it's a method or not,
  1476. ¥  so that we're always 8-byte aligned.  This way we make sure we aren't
  1477. ¥  going to run into what's underneath us on the rtn stack.
  1478.  
  1479.     tempObjs dlen 16 + #align8 -> tempObj_framesize
  1480.     local? NIF                            ¥ set up for entry unless we're in
  1481.         PLentry  initTemps                ¥  a local section (then it gets done
  1482.     THEN                                ¥  by :LOC)
  1483.     ['] releaseTemps -> releaseTemps_xt
  1484.                             ¥ (;) compiles a call to there at semicolon time
  1485.     postpone ]                            ¥ start compiling
  1486. ;
  1487.  
  1488.  
  1489. : TEMP{        immed
  1490.  
  1491. (*    First we have to allocate an internal local variable as a frame pointer.
  1492.     There are 4 situations.  There may or may not already be locals, and
  1493.     we may or may not be in a local section.  Note we can be in a local
  1494.     section even if there aren't already locals, since the purpose of the
  1495.     local section might be just to establish a section for these temp objects.
  1496.  
  1497.     If there are already locals, we just add another.  If we're not in a
  1498.     local section we need to recompile the entry sequence (done by PLentry)
  1499.     since the number of regs to be saved and set up is different.  But if
  1500.     we're in a local section, we don't have to recompile since we haven't
  1501.     called PLentry yet, so we just add the extra local.  If there aren't any
  1502.     locals already, we just call initLocs which sets them up, before adding
  1503.     the new one.
  1504. *)
  1505.     resetTemps
  1506.     #PL NIF  initLocs  THEN            ¥ No locs before, so set up for them now
  1507.  
  1508.     local? IF  -1 -> local?  THEN    ¥ If in a local section, setting local?
  1509.                                     ¥ to -1 means we've defined the locals
  1510.                                     ¥ so can't do it again
  1511.     true -> locFlg                    ¥ it's a local, not a parm
  1512.     " x " pad place  pad addToParmList    ¥ pseudo local variable - name has
  1513.                                         ¥  a space so can't conflict
  1514.     32 #PL -                        ¥ this is the GPR# for the frame pointer
  1515.     dup -> TO_gpr#                    ¥ save it
  1516.     <'> locReg  3+ c!                ¥ and plug into locReg dic entry
  1517.  
  1518. (*    Next we save CDP and move halfway up in the free dic space - we'll put
  1519.     the "ivar dic entries" for the temp objs there - we don't need them
  1520.     after the defn is compiled.
  1521. *)
  1522.     CDP                $ 2000 ++> CDP  code_align
  1523.     curr-def
  1524.     cstate            true -> cstate
  1525.     ^comp_class
  1526.     ['] } >body @                ¥ save old action for "}"
  1527.     ['] }temp  -> }                ¥ "}" will now be same as }temp
  1528.     130                            ¥ for ?pairs
  1529.  
  1530.     ['] dummy dup    -> ^comp_class    ¥ local objs will look like ivars of Dummy
  1531.                     -> tempObjs        ¥ this will enable finding them
  1532.     postpone [                        ¥ stop compiling
  1533. ;
  1534.  
  1535.                             
  1536. : TEMP        gobble{  postpone temp{  ;        immediate
  1537.  
  1538. ¥ set_CD_gpr# sets the GPR we're going to use for this definition to
  1539. ¥  point to the start of the constant data.  We make it an internal
  1540. ¥  local variable, so the code is very similar to TEMP{ above.
  1541.  
  1542. variable tempv
  1543.  
  1544. :f set_CD_gpr#
  1545.  
  1546.     CD_gpr#  ?EXIT                    ¥ out if we've already done it
  1547.  
  1548.     #PL NIF  initLocs  THEN            ¥ No locs before, so set up for them now
  1549.  
  1550.     local? IF  -1 -> local?  THEN    ¥ If in a local section, setting local?
  1551.                                     ¥ to -1 means we've defined the locals
  1552.                                     ¥ so can't do it again
  1553.     true -> locFlg                    ¥ it's a local, not a parm
  1554.     " q " tempv place  tempv addToParmList
  1555.                                     ¥ pseudo local variable - name has
  1556.                                     ¥  a space so can't conflict
  1557.     32 #PL -                ¥ this is the GPR# for the const data pointer
  1558.     dup -> CD_gpr#
  1559.     select: GPRs  permanent: GPRs
  1560. ;f
  1561.  
  1562.  
  1563. (*
  1564. ¥ testing temp objects with indexing:
  1565. +echo
  1566.  
  1567. : q
  1568. temp{    10 array aa
  1569.         5  array bb
  1570. }
  1571.  
  1572.     5 at: aa  4 to: bb
  1573. ;
  1574.  
  1575. : qq db q ;
  1576.  
  1577. endload
  1578. *)
  1579.  
  1580.  
  1581. (*        =================  Records and unions  ====================
  1582.  
  1583. Syntax:
  1584.  
  1585.     record <name>        ¥ The name is optional
  1586.    {    var        v1
  1587.         int        i1
  1588.         string    s
  1589.    }
  1590.    
  1591.        union <name>        ¥ The name is optional
  1592.    {    var        v1
  1593.         int        i1
  1594.         string    s
  1595.    }
  1596.  
  1597.  
  1598. Or you can use record{ ...  } or union{ ... } if you prefer, if it's
  1599. unnamed.  The similarity of syntax to temp objects is quite deliberate.
  1600. But any similarity to Your Favorite Language is entirely accidental.  Well
  1601. actually it's not, but I think this syntax is as good as any, and probably
  1602. more readable for folks coming from the land of C.
  1603.  
  1604. unions can be nested within records and vice versa.
  1605.  
  1606. NOTE: it's best to not use unions unless you're really sure you know what
  1607. you're doing.  Having different objects sharing the same memory is sure
  1608. to cause problems if you're careless!
  1609.  
  1610. *)
  1611.  
  1612. : SVREC        
  1613.     ^comp_class dfa w@ 
  1614.     rec?  union?  unionOffs  68k_align?
  1615. ;
  1616.  
  1617. : RSTREC
  1618.     -> 68k_align?  -> unionOffs  -> union?  -> rec?  
  1619.     union? IF     ¥ we fell back in a union, so we
  1620.                 ¥ reset data pointer to where it was at the beginning
  1621.                 ¥ of this union/rec
  1622.         ^comp_class dfa w!
  1623.     ELSE
  1624.         drop
  1625.     THEN
  1626. ;
  1627.  
  1628. : ?HANDLE_NAME  { ¥ sv_>in sv_^class sv_rec? -- }
  1629.     >in @ -> sv_>in ^comp_class -> sv_^class  rec? -> sv_rec?
  1630.     Mword  count  " {" s=
  1631.     NIF                            ¥ we've got a name for the record
  1632.         true -> rec?            ¥ must do this before defining the name "object"
  1633.         sv_>in  >in !
  1634.         " object" sFind drop  ivDef
  1635.         sv_rec? -> rec?  sv_^class -> ^comp_class
  1636.         gobble{                    ¥ "{" must follow
  1637.     THEN
  1638. ;
  1639.  
  1640.  
  1641. : }RECORD
  1642.     131 ?pairs  rstRec
  1643.     ['] } >body !  ;
  1644.  
  1645.  
  1646. : RECORD{
  1647.     ?class                        ¥ must be compiling a class
  1648.     ['] } >body @                ¥ save old action for "}"
  1649.     ['] }record  -> }            ¥ "}" will now be same as }record
  1650.     svRec                        ¥ save parameters for any existing record/union
  1651.     131                            ¥ for ?pairs
  1652.     true -> rec?  false -> union?  ;
  1653.  
  1654. : RECORD
  1655.     ?handle_name
  1656.     record{  ;
  1657.  
  1658. : 68k_RECORD{
  1659.     record{
  1660.     true -> 68k_align?  ;
  1661.  
  1662. : 68k_RECORD
  1663.     record
  1664.     true -> 68k_align?  ;
  1665.  
  1666.  
  1667. : }UNION
  1668.     132 ?pairs
  1669.     unionOffs  ^comp_class dfa w!    
  1670.     rstRec
  1671.     ['] } >body !  ;            ¥ restore old action for "}"
  1672.  
  1673. : UNION{
  1674.     ?class                        ¥ must be compiling a class
  1675.     ['] } >body @                ¥ save old action for "}"
  1676.     ['] }union  -> }            ¥ "}" will now be same as }union
  1677.     svRec                        ¥ save record/union parameters
  1678.     132                            ¥ for ?pairs
  1679.     true -> rec?  true -> union?
  1680.     ^comp_class dfa w@ -> unionOffs  ;
  1681.  
  1682.  
  1683. : UNION
  1684.     ?handle_name
  1685.     union{  ;
  1686.  
  1687.  
  1688. (*        =================  Static ivars ====================
  1689.  
  1690. Syntax:
  1691.  
  1692.     static
  1693.    {    var        v1
  1694.         int        i1
  1695.         string    s
  1696.    }
  1697.  
  1698. Or you can use  static{ ...  } if you prefer.
  1699.  
  1700. These are like static class variables in C++ - they belong to the class,
  1701. not the object, and thus are shared by all objects of the class.  We
  1702. allocate each ivar in the dictionary right after its ivar header.
  1703. *)
  1704.  
  1705. : }STATIC
  1706.     133 ?pairs
  1707.     ['] } >body !                    ¥ restore old action for "}"
  1708.     false -> static?  ;
  1709.  
  1710.  
  1711. : STATIC{
  1712.     ?class                        ¥ must be compiling a class
  1713.     ['] } >body @                    ¥ save old action for "}"
  1714.     ['] }static  -> }            ¥ "}" will now be same as }static
  1715.     133                            ¥ for ?pairs
  1716.     true -> static?  ;
  1717.  
  1718. : STATIC
  1719.     gobble{  static{  ;
  1720.  
  1721.  
  1722. ¥            ==========================================
  1723.  
  1724. ¥ CL1 is our first stage cleanup word - called on an abort.  Resets things
  1725. ¥ to normal.  Later cleanup words do their special stuff, then call CL1.
  1726. ¥ Actually on the PPC it's not quite the first, since we've loaded pFiles
  1727. ¥ already, and so have already introduced clFiles as the file cleanup
  1728. ¥ word.  On the 68k it was really the first.
  1729.  
  1730. : CL1
  1731.     (;cl)  clrComp  ['] (}) -> }
  1732.     0 -> bufPtr  0 -> hiCDP        ¥ for interpreting message binds
  1733.     resetTemps
  1734.     false -> rec?  false -> union?
  1735.     false -> 68k_align?  false -> compinline?
  1736.     0 -> extraFind
  1737.     0 -> bufPtr
  1738.     false -> case_in_names?
  1739.     clFiles
  1740. ;
  1741.  
  1742. ' cl1  -> abortVec
  1743.  
  1744.  
  1745. torture? not [IF]  endload  [THEN]
  1746.  
  1747.  
  1748. (* ***********
  1749.  
  1750. ¥ A simple test of the basic class stuff - run if the plot
  1751. ¥  gets totally lost:
  1752.  
  1753. :class nothingClass super{ object }
  1754. ;class
  1755.  
  1756. :class testClass super{ object }
  1757. :m aa: 1 2 3 ;m
  1758. :m bb: 99  aa: self  ;m
  1759. ;class
  1760.  
  1761. testClass ttt
  1762. bb: ttt            ¥ should leave ( -- 1 2 3 99 )
  1763.  
  1764.  
  1765. :class cl2 super{ testClass }
  1766.   testClass bloggs
  1767. :m cc:  $ 1234
  1768.         bb: bloggs
  1769.         bb: super
  1770. ;m
  1771. ;class
  1772.  
  1773. cl2  myObj
  1774. cc: myObj
  1775.  
  1776.  
  1777. ********** *)
  1778.  
  1779.  
  1780.  
  1781. ¥ ===============================================================
  1782. ¥                        TORTURE TESTS
  1783. ¥ ===============================================================
  1784.  
  1785.  
  1786. : ?CHK
  1787.     2dup <>
  1788.     IF    cr .h cr .h
  1789.         true abort" check FAILED!!!"        ¥ error if something doesn't
  1790.                                             ¥  give what we expect
  1791.     ELSE
  1792.         2drop
  1793.     THEN
  1794. ;
  1795.  
  1796.  
  1797. :class    VAR    super{ object }
  1798.  
  1799.     4 bytes data
  1800.  
  1801. :m CLEAR:
  1802.     inline{ 0 ^base !}  ;m
  1803.  
  1804. :m GET:
  1805.     inline{ ^base @}  ;m
  1806.  
  1807. :m PUT:
  1808.     inline{ ^base !}  ;m
  1809.  
  1810. :m GETT:    ^base @  ;m
  1811.     
  1812. :m PUTT:    ^base !  ;m
  1813.  
  1814. :m +:
  1815.     inline{ ^base +!}  ;m
  1816.  
  1817. :m -:
  1818.     inline{ ^base -!}  ;m
  1819.  
  1820. :m ->:
  1821.     inline{ @ ^base !}  ;m
  1822.  
  1823. :m TEST:  @ ^base !  ;m
  1824.  
  1825. mlocal LOCTEST:  { aa ¥ bb cc -- }
  1826.  
  1827. :m AAA:    aa -> bb  ;m
  1828.  
  1829. :mloc  LOCTEST:        ¥ should double the number passed in and store in self
  1830.     aaa: self  ¥ ." loctest: here!" cr  
  1831.     bb -> cc  bb ++> cc
  1832.     cc  ^base !
  1833. ;mloc
  1834.  
  1835. mlocal LOCTEST2:  { aa bb cc dd ee ff ¥ gg hh ii -- }
  1836.  
  1837. :m bbb:
  1838.     aa bb +  cc *  -> gg
  1839.     dd ee +  ff *  -> hh
  1840.     gg hh +  -> ii
  1841.     " hi there"
  1842. ;m
  1843.  
  1844. :mloc  loctest2:
  1845.     bbb: self  ii ^base !
  1846.     " ho ho"
  1847. ;mloc
  1848.  
  1849.     
  1850. :m PRINT:
  1851.     ^base @  .  ;m
  1852.  
  1853. :m CLASSINIT:
  1854.     $ 123  put: self  ;m
  1855.  
  1856. ;class
  1857.  
  1858.  
  1859. :class    BYTE    super{ object }
  1860.  
  1861.     1 bytes data
  1862.  
  1863. :m CLEAR:
  1864.     inline{ 0 ^base c!}  ;m
  1865.  
  1866. :m GET:
  1867.     inline{ ^base c@x}  ;m
  1868.  
  1869. :m UGET:
  1870.     inline{ ^base c@}  ;m
  1871.  
  1872. :m PUT:
  1873.     inline{ ^base c!}  ;m
  1874.  
  1875. :m ->:
  1876.     inline{ c@ ^base c!}  ;m
  1877.  
  1878. :m PRINT:
  1879.     ^base c@  .        ;m
  1880.  
  1881. :m CLASSINIT:    9 put: self  ;m
  1882.  
  1883. ;class
  1884.  
  1885.  
  1886. ¥ some very simple testing, to start with:
  1887.  
  1888. 0        value    testVal
  1889.         var        aVar
  1890.         byte    aByte
  1891.  
  1892. : test1
  1893. ." test1" cr
  1894.     987 avar !  get: avar  987 ?chk            ¥ optimizes
  1895.     addr: avar  -> testVal
  1896.     876 testVal !                            ¥ should clobber opt
  1897.     get: avar  876  ?chk
  1898. ;
  1899.  
  1900. : test2            ¥ testing late binding - assumes test1 done
  1901. ." test2" cr
  1902.     get: [ avar ]  876  ?chk
  1903. ¥ now, does the late-bind cache work?
  1904.     get: [ avar ]  876  ?chk
  1905. ;
  1906.  
  1907.  
  1908. local  localTest { ¥ aa bb cc dd -- }
  1909.  
  1910. : aaa    " hahaha"  ;
  1911.  
  1912. :loc localTest
  1913.         aaa  " hoho"
  1914. ;loc
  1915.  
  1916.  
  1917. : test3            ¥ testing local methods, and local sections with const
  1918.                 ¥  data.  Note: we can assume ordinary local sections
  1919.                 ¥  work, since we use them in the class stuff so we wouldn't
  1920.                 ¥  have made it to here unless they work!!
  1921. ." test3" cr
  1922.     222 loctest: aVar  get: aVar  444 ?chk
  1923.     20 30 3            ¥ -> 150
  1924.     10 30 4            ¥ -> 160
  1925.     loctest2: aVar  get: aVar 310 ?chk
  1926.     " ho ho" s=    -1 ?chk
  1927.     " hi there" s= -1 ?chk
  1928.     localtest    " hoho" s=  -1 ?chk
  1929.                 " hahaha" s=  -1 ?chk
  1930. ;
  1931.  
  1932.  
  1933. var vv
  1934.  
  1935. :class    BOOL    super{ byte }
  1936.  
  1937. :m GET:
  1938.     inline{ ^base c@x}  ;m
  1939.  
  1940. :m PUT:
  1941.     inline{ 0<> ^base c!}  ;m
  1942.  
  1943. :m SET:
  1944.     inline{ true ^base c!}  ;m
  1945.  
  1946. :m PRINT:
  1947.     get: self  IF  ." true"  ELSE  ." false"  THEN  ;m
  1948.  
  1949. :m CLASSINIT:    clear: self  ;m
  1950.  
  1951. ;class
  1952.  
  1953.  
  1954. :class    BARRAY  super{ object }  1 indexed
  1955.  
  1956. :m  AT:        ¥ ( index -- n )
  1957.     inline{ ^elem c@}  ;m
  1958.  
  1959. :m  TO:        ¥ ( n index -- )
  1960.     inline{ ^elem c!}  ;m
  1961.  
  1962.  
  1963. :m ^ELEM:    ¥ ( index -- addr )
  1964.     inline{ ^elem}  ;m
  1965.  
  1966. :m FILL:    ¥ ( value -- )  Fills all elements with value.
  1967.     idxbase  limit 2*  bounds
  1968.     ?DO  dup  i c!  LOOP  drop  ;m
  1969.  
  1970. :m WIDTH:    1  ;m        ¥ Faster than the default in Object
  1971.  
  1972. :m GETELEM:    ¥ ( addr -- n )  Fetches one element at addr
  1973.     c@x  ;m
  1974.  
  1975. :m TEST:    at: self  ;m
  1976.  
  1977. ;class
  1978.  
  1979.  
  1980. ¥ Testing arrays:
  1981.  
  1982. 20 barray bb
  1983.  
  1984. : test4
  1985. ." test4" cr
  1986.     $ 9887 bb 20 + c!
  1987.     12 -> testVal
  1988.     testVal test: bb  $ 87 ?chk
  1989.     120 -> testVal
  1990. ¥    ." should fail range check and trap - just step past the tw:" cr cr
  1991. ¥    testval test: bb        ¥ range check now omitted since Jasik doesn't
  1992.                             ¥  like it.  Try it after we've loaded our
  1993.                             ¥  exception handler in zObjInit.
  1994. ;
  1995.  
  1996.  
  1997. ¥ also we test indexed classes which are subclassed and have
  1998. ¥  added ivars, to make sure we get the right offset to the
  1999. ¥  indexed header:
  2000.  
  2001. :class    INDEXED-OBJ  super{ object }
  2002.  
  2003. :m ^ELEM:    ^elem  ;m
  2004.  
  2005. :m LIMIT:    limit  ;m
  2006.  
  2007. :m WIDTH:    idxbase  6 -  w@  ;m
  2008.  
  2009. :m IXADDR:    idxbase  ;m
  2010.  
  2011. :m CLEARX:    ¥ Erases indexed area.
  2012.     idxbase  limit  width: self  *  erase  ;m
  2013.  
  2014. :m CLASSINIT:    clearX: self  ;m
  2015.  
  2016. ;class
  2017.  
  2018.  
  2019. :class    WARRAY  super{ indexed-obj }  2 indexed
  2020.  
  2021. :m AT:        ¥ ( index -- n )
  2022.     inline{ ^elem w@x}  ;m
  2023.     
  2024. :m ATT:        ^elem w@x  ;m
  2025.  
  2026. :m TO:        ¥ ( n index -- )
  2027.     inline{ ^elem w!}  ;m
  2028.  
  2029. ;class
  2030.  
  2031.  
  2032. :class  TRIGTABLE    super{ wArray }
  2033.  
  2034.     3    wArray  AXISVALS
  2035. ;class
  2036.  
  2037. 10 trigtable ttt
  2038. $ 56  ttt $ 26 + w!
  2039.  
  2040. : test5 { ¥ xx -- }
  2041.     ." test5" cr
  2042.     addr: ttt  -> xx        ¥ so we can look at it in the debugger
  2043.     3 at: ttt  $ 56 ?chk  ;
  2044.  
  2045.  
  2046. ¥ Testing object pointers
  2047.  
  2048. var        vv1
  2049.  
  2050. objPtr    ov    class_is var
  2051. objPtr    ov1    class_is var
  2052.  
  2053. objPtr    ob    class_is bool
  2054.  
  2055.  
  2056. : test6
  2057.     ." test6" cr
  2058.     $ 765 put: vv  $ 543 put: vv1
  2059.     vv1 -> ov1  vv -> ov
  2060.     gett: ov1  $ 543  ?chk  get: ov  $ 765 ?chk
  2061.     $ 345 putt: ov  get: ov  $ 345 ?chk  ;
  2062.  
  2063.  
  2064. ¥ Testing static and public ivars
  2065.  
  2066. :class SIVTEST  super{ var }
  2067. public
  2068. static
  2069. {    var        V1
  2070.     bool    B1
  2071.     byte    B2
  2072. 10    barray    BB
  2073. }
  2074.     bool    BLOC
  2075.     var        VLOC
  2076.     
  2077. :m QQ:    get: v1  get: b1  get: b2 4 at: bb
  2078.         get: vloc  ;m
  2079.  
  2080. :m TEST:
  2081.         66 put: v1  77 put: vloc  ;m
  2082.  
  2083. :m CLASSINIT:
  2084.         32 put: v1  set: b1  33 put: b2  34 4 to: bb
  2085.         set: bloc  34 put: vloc  ;m
  2086. ;class
  2087.  
  2088.  
  2089. sivtest zzz
  2090. sivtest sss
  2091.  
  2092. objPtr myop  class_is sivtest
  2093.  
  2094. : QQQ
  2095. ¥    classinit: zzz  classinit: sss        ¥ needed in qpClass, but not here
  2096.     get: ivar> v1 in_class sivtest
  2097.     test: sss
  2098.     get: ivar> b2 in_class sivtest
  2099.     get: ivar> v1 in_class sivtest
  2100.     zzz get: ivar> bloc in class_as> sivtest
  2101.     sss get: ivar> vloc in class_as> sivtest  ;
  2102.  
  2103. : test7
  2104.     ." test7" cr
  2105.     qqq
  2106.     77  ?chk
  2107.     -1    ?chk
  2108.     66    ?chk
  2109.     33    ?chk
  2110.     32  ?chk
  2111. ;
  2112.  
  2113.  
  2114. :class HAHA  super{ object }
  2115.  
  2116.     sivtest    IVsss
  2117.     
  2118. :m QQ:      test: IVsss  get: ivar> vloc IN ivsss  ;m
  2119. ;class
  2120.  
  2121. haha hh
  2122.     
  2123. : test8
  2124.     ." test8" cr
  2125.     classinit: zzz   qq: hh  77 ?chk
  2126.     get: ivar> vloc IN zzz
  2127.     34 ?chk
  2128. ;
  2129.  
  2130.  
  2131. ¥ Testing late bind to self
  2132.  
  2133. :class VAR+ super{ var }
  2134.  
  2135. :m QQ:    get: [self]        ¥ should make class general
  2136.         get: [ self ]    ¥ shouldn't give any error
  2137. ;m
  2138.  
  2139. ;class
  2140.  
  2141. var+ VVV
  2142.  
  2143. ¥ qq: vvv        ¥ no need for ?chk since it will give its own error
  2144.  
  2145. : test9
  2146.     ." test9" cr
  2147.     qq: vvv  2drop
  2148. ;
  2149.  
  2150.  
  2151. ¥ Testing records and unions.  Also, the TEST: method piles up so many
  2152. ¥  values that this also tests register spilling with a duplicate value!
  2153.  
  2154. :class RECTEST super{ object }
  2155.     var    vv
  2156.     record RR
  2157.     {        var        v1
  2158.             bool    b1
  2159.         3    barray  bbb
  2160.             byte    b3            ¥ now aligned - unions should normally
  2161.                                 ¥  start out aligned, but we don't insist
  2162.                                 ¥  on it
  2163.         union {    byte    b2
  2164.                 var        v2
  2165.                 record {    byte bb1
  2166.                             byte bb2    }
  2167.             }
  2168.             var        v3
  2169.     }
  2170.  
  2171.  
  2172. :m TEST:
  2173.     4 0 to: bbb  5 1 to: bbb  6 2 to: bbb
  2174.     $ 33  put: vv
  2175.     $ 123 put: v1  set: b1
  2176.     $ 124 put: v2  7 put: b3
  2177.     $ 35 put: bb1  $ 36 put: bb2
  2178.     $ 125 put: v3  $ 37 put: b2
  2179.     get: v1  put: b1
  2180.     get: b2  get: v2
  2181.     get: bb1  get: bb2  get: v3
  2182.     addr: rr  36 + @
  2183. ;m
  2184. ;class
  2185.  
  2186. recTest rrr
  2187.  
  2188. : test10
  2189.     ." test10" cr
  2190.     $ 33  addr: vvv !
  2191.     qq: vvv
  2192.     $ 33        ?chk
  2193.     $ 33        ?chk
  2194.     test: rrr
  2195.     $ 125        ?chk
  2196.     $ 125        ?chk
  2197.     $ 36        ?chk
  2198.     $ 37        ?chk
  2199.     $ 37360124    ?chk
  2200.     $ 37        ?chk
  2201.     rrr $ 2C + @  $ 04050607  ?chk
  2202. ;
  2203.  
  2204.  
  2205. ¥ testing multiple inheritance
  2206.  
  2207. :class INT  super{ object }
  2208.  
  2209.     2    bytes    data
  2210.  
  2211. :m CLEAR:
  2212.     inline{ 0 ^base ! }  ;m
  2213.  
  2214. :m UGET:
  2215.     inline{ ^base w@ }  ;m
  2216.  
  2217. :m GET:
  2218.     inline{ ^base w@x }  ;m
  2219.  
  2220. :m PUT:
  2221.     inline{ obj w! }  ;m
  2222.  
  2223. :m PUTT:    ^base w!  ;m
  2224. :m IPUT:    ^base w!  ;m        ¥ used in testing mult inheritance
  2225.  
  2226. :m CLASSINIT:  $ 456 put: self  ;m
  2227.  
  2228. ;class
  2229.  
  2230.  
  2231. :class CC  super{ byte int var bool }
  2232.  
  2233. :m TEST:
  2234. iput: self    ¥ check it compiles
  2235.     uget: self            ¥ offs should be 0
  2236.     +: self                ¥ offs should be 4
  2237.     set: self  ;m        ¥ offs should be E
  2238.  
  2239. :m TEST1:
  2240.     set: self
  2241.     get: super> bool    ¥ should get -1
  2242.     get: super
  2243. ;m
  2244.     
  2245. :m setValues:
  2246.     9 put: super> byte
  2247.     $ 456  putt: super        ¥ should go to the int
  2248.     $ 456  put: super> int
  2249.     $ 123  put: super> var
  2250.     set: super
  2251. ;m
  2252.  
  2253. ;class
  2254.  
  2255. cc myCC
  2256.  
  2257. : test11 { ¥ addr -- }
  2258.     ." test11" cr
  2259.     addr: mycc -> addr
  2260.     setValues: mycc
  2261.     mycc @        $ 09000000    ?chk
  2262.     mycc 4+   @    $ fff40002  ?chk
  2263.     mycc 8 +  @    $ 04560000    ?chk
  2264.     mycc 12 + @ $ ffec0002  ?chk
  2265.     mycc 16 + @    $ 123        ?chk
  2266.     mycc 20 + @ $ ffe40002  ?chk
  2267.     mycc 24 + @ $ ff000000  ?chk
  2268. ;
  2269.  
  2270.  
  2271. :class STRANGE  super{ object }
  2272.     var VV
  2273.     byte BB
  2274. :m GET:  get: vv  get: bb  ;m
  2275. :m PUT:  put: bb  put: vv  ;m
  2276.  
  2277. ;class
  2278.  
  2279.  
  2280. :class    ARRAY  super{ indexed-obj }  4 indexed
  2281.  
  2282. :m AT:        ¥ ( index -- n )
  2283.     inline{ ^elem @}  ;m
  2284.     
  2285. :m ATT:        ^elem @  ;m
  2286.  
  2287. :m TO:        ¥ ( n index -- )
  2288.     inline{ ^elem !}  ;m
  2289.  
  2290. :m  +TO:        ¥ ( n index -- )
  2291.     inline{ ^elem +!}  ;m
  2292.  
  2293. :m -TO:        ¥ ( n index -- )
  2294.     inline{ ^elem -!}  ;m
  2295.  
  2296. :m FILL:        ¥ ( value -- )  Fills all elements with value.
  2297.     idxbase  limit 4*  bounds
  2298.     DO  dup  i !  4 +LOOP  drop  ;m
  2299.  
  2300.  
  2301. :m ATEST:
  2302.     1 at: self  ;m
  2303.  
  2304. ;class
  2305.  
  2306.  
  2307. :class MULT    super{ var int array }
  2308.  
  2309. :m MTEST:    $ 456  put: super> int  $ 123  put: super> var
  2310.             uget: super  999 1 to: self  ;m
  2311.             
  2312. :m MAT:        at: self  ;m
  2313.  
  2314. ;class
  2315.  
  2316.  
  2317. objPtr    OO    class_is mult
  2318. objPtr    OOO    class_is int
  2319.  
  2320. :class IVXX    super{ object }
  2321.     10 bytes data2
  2322.     int    i1
  2323.     int    i2
  2324.     130 bytes qqqq        ¥ Include to check >128 distance
  2325.                         ¥  index addressing of array qwert
  2326.     9 array qwert
  2327.  
  2328. :m ITEST:
  2329.     $ 8456  dup i1 w!  addr: i2 w!        ¥ should be equivalent
  2330.     get: i1  uget: i2  66 put: i2
  2331.     99 3 to: qwert  1234 drop  3 at: qwert
  2332.     addr: i2  -> ooo  ;m
  2333.  
  2334. :m GETQWERT:
  2335.     addr: qwert  ;m
  2336. ;class
  2337.  
  2338.  
  2339. int ii
  2340. 3 mult    mm
  2341. ivxx    iv
  2342.  
  2343. : test12
  2344.     ." test12" cr
  2345.     itest: iv
  2346.     $ 63    ?chk
  2347.     $ 8456    ?chk
  2348.     $ ffff8456    ?chk
  2349.     mtest: mm
  2350.     $ 456    ?chk
  2351.     88 iput: mm        ¥ Note: get: mm will bind to the var, but uget: mm
  2352.                     ¥ will bind to the int and give 88.
  2353.  
  2354.     get: mm  $ 123    ?chk
  2355.     uget: mm 88        ?chk
  2356. ;
  2357.  
  2358. : test13
  2359. ." test13" cr
  2360.     itest: iv
  2361.     getqwert: iv  3 swap at: **        99    ?chk
  2362.     mtest: mm            $ 456    ?chk
  2363.     1 at: mm            999 ?chk
  2364.     1 mat: mm            999 ?chk
  2365.     1 mm at: mult        999 ?chk
  2366.     1 mm at: []            999 ?chk
  2367.     mm -> oo
  2368.     1 at: oo            999     ?chk
  2369.     1 mat: oo            999     ?chk
  2370.     uget: mm            $ 456    ?chk
  2371.     addr: mm  addr: oo            ?chk  ¥ Both numbers shd be same
  2372.     uget: ooo            66        ?chk
  2373. ;
  2374.  
  2375.  
  2376. ¥ testing ivSetup (via deep_classinit: ) - this should put the $123 and
  2377. ¥  $456 in the var and the int, and store the same offsets in the header
  2378. ¥  that are already there.
  2379.  
  2380. :class ivsTestClass  super{ var int array }
  2381.     record
  2382.     {    var        v1
  2383.         int        i1
  2384.         byte    b1
  2385.      3     array    a1
  2386.     }
  2387. ;class
  2388.  
  2389. 5 ivsTestClass  ivs1
  2390.  
  2391. : test14 { ¥ aa -- }
  2392. ." test14" cr
  2393.     deep_classinit: ivs1
  2394.     addr: ivs1 @        $ 123          ?chk
  2395.     addr: ivs1 4 + @    $ FFF4003A    ?chk
  2396.     addr: ivs1 8 + @    $ 04560000    ?chk
  2397.     addr: ivs1 12 + @    $ FFEC0032    ?chk
  2398.     addr: ivs1 16 + @    $ 123        ?chk
  2399.     addr: ivs1 20 + @    $ 04560900    ?chk
  2400.     addr: ivs1 24 + @    $ 0            ?chk    ¥ array has no name so zero here
  2401.     addr: ivs1 -> aa
  2402.     addr: ivs1 28 + c@    $ 08        ?chk    ¥ rest of reloc addr can change
  2403.     addr: ivs1 32 + @    $ FFFC000A    ?chk
  2404.     addr: ivs1 36 + @    $ 4            ?chk
  2405.      addr: ivs1 40 + @    $ 2            ?chk
  2406.  ;
  2407.  
  2408.  
  2409. ¥ Testing temp objects
  2410.  
  2411. :class strxx super{ string }
  2412.  
  2413. :m RELEASE:
  2414.     ." string released" cr  release: super
  2415. ;m
  2416. ;class
  2417.  
  2418. : leaf ;
  2419.  
  2420. : test15 { ¥ aa bb -- }
  2421. temp
  2422. {    var    v1
  2423.      var    v2
  2424.      strxx s1
  2425. }
  2426.     ." test15" cr
  2427.     get: v1  get: v2
  2428.     $ 123    ?chk
  2429.     $ 123    ?chk
  2430. db
  2431. leaf
  2432.     " hello world!" put: s1
  2433.     ." The next line should say hello world!" cr
  2434.     get: s1 type cr
  2435.     ." The next line should say string released" cr
  2436. ;
  2437.  
  2438. :class AAAA super{ object }
  2439.  
  2440. :m CLICK:  { ¥ part ^ctl action1 action2 x y -- }
  2441.     null
  2442. ;m
  2443.  
  2444. ;class
  2445.  
  2446. aaaa myAAAA
  2447. : test16
  2448. ." test16" cr
  2449.     click: myAAAA   ;
  2450.  
  2451.  
  2452. ¥ =========== TORTURE runs the test! ============
  2453.  
  2454. : TORTURE
  2455.     ." torture tests start..." cr cr
  2456.     test1 test2 test3 test4 test5
  2457.     test6 test7 test8 test9
  2458.     test10 test11 test12 test13
  2459.     test14  test15  test16
  2460.     cr cr ." torture tests WORKED!!!" cr
  2461. ;
  2462.  
  2463.  
  2464. +echo
  2465. : leaf ;
  2466.  
  2467. : BUG  { ¥ neg? -- %x' }
  2468.     fdrop
  2469.     neg? if leaf then
  2470. ;
  2471.